use std::collections::HashMap;

pub struct Blackboard {
    memory: HashMap<String, serde_json::Value>
}

impl  Blackboard {
    pub fn new() -> Blackboard {
        Blackboard {
            memory: HashMap::new()
        }
    }

    fn get_memory_mut_ref(&mut self, tree_scope: &String, node_scope: &String) -> Option<&mut serde_json::Value> {
        if !self.memory.contains_key(tree_scope) {
            self.memory.insert(tree_scope.to_string(),json!({
                node_scope: {}
            }));
        }
        match self.memory.get_mut(tree_scope) {
            Some(_m) => {
                if node_scope.len() > 0 {
                    match _m.as_object_mut() {
                        Some(_nm_obj) => {
                            if !_nm_obj.contains_key(node_scope) {
                                _nm_obj.insert(node_scope.to_string(), json!({}));
                            }
                            match _nm_obj.get_mut(node_scope) {
                                Some(_r) => {
                                    // println!("111111 222222 3333 {:?} {:?} {:?}", tree_scope, node_scope, json!(_r).to_string());
                                    return Some(_r);
                                }
                                None => {
                                    None
                                }
                            }
                        }
                        None => {
                            None
                        }
                    }
                } else {
                    Some(_m)
                }
            }
            None => {
                None
            }
        }
    }

    pub fn get(&self, key: &String, tree_scope: &String, node_scope: &String) -> Option<&serde_json::Value> {
        match self.memory.get(tree_scope) {
            Some(_m) => {
                if node_scope.len() > 0 {
                    match _m.get(node_scope) {
                        Some(_nm) => {
                            // println!("getgetget {:?} {:?} {:?} {:?}", tree_scope, node_scope, key, json!(_nm).to_string());
                            _nm.get(key)
                        }
                        None => {
                            None
                        }
                    }
                } else {
                    // println!("getgetget tree {:?} {:?}", key, json!(_m).to_string());
                    _m.get(key)
                }
            }
            None => {
                None
            }
        }
    }

    pub fn set(&mut self, key: &String, value: serde_json::Value, tree_scope: &String, node_scope: &String) {
        match self.get_memory_mut_ref(tree_scope, node_scope) {
            Some(_m) => {
                match _m.as_object_mut() {
                    Some(_obj) => {
                        // println!("setsetset {:?} {:?} {:?} {:?} {:?}", key, tree_scope, node_scope, value.to_string(), json!(_obj).to_string());
                        _obj.insert(key.to_string(), value);
                        // println!("setsetset 111 {:?} {:?} {:?} {:?}", key, tree_scope, node_scope, json!(_obj).to_string());
                    }
                    None => {
                        println!("set @@@@@@@@@ none as_object_mut");
                    }
                }
            }
            None => {
                println!("set @@@@@@@@@ none");
            }
        }
    }

    pub fn delete(&mut self, key: &String, tree_scope: &String, node_scope: &String) {
        match self.get_memory_mut_ref(tree_scope, node_scope) {
            Some(_m) => {
                match _m.as_object_mut() {
                    Some(_obj) => {
                        _obj.remove(key);
                    }
                    None => {}
                }
            }
            None => {}
        }
    }
}